import multer from "koa-multer"
import path from "path"
import fs from "fs"

export const UPLOAD_DIR = "public/upload"
const uploadStatuses: Record<string, Record<number, boolean>> = {}

// 配置multer存储
const storage = multer.diskStorage({
  destination: (
    // @ts-ignore
    req: any,
    // @ts-ignore
    file: multer.File,
    cb: (err: Error | null, destination: string) => void
  ) => {
    cb(null, UPLOAD_DIR)
  },
  filename: (
    // @ts-ignore
    req: any,
    file: multer.File,
    cb: (err: Error | null, filename: string) => void
  ) => {
    const id = new Date().getTime() + Math.round(Math.random() * 1e9)
    cb(null, `${file.fieldname}-${id}${path.extname(file.originalname)}`)
  }
})

export const chunkUpload = async function (
  file: Buffer,
  chunkPath: string
): Promise<void> {
  return new Promise((resolve, reject) => {
    const writeStream = fs.createWriteStream(chunkPath)
    writeStream.on("finish", resolve)
    writeStream.on("error", reject)
    writeStream.write(file)
    writeStream.end()
  })
}

export const chunkUploadStatus = function (
  filename: string,
  chunkIndex: number,
  chunkTotal: number
): Promise<void> | void {
  if (!uploadStatuses[filename]) uploadStatuses[filename] = {}
  uploadStatuses[filename][chunkIndex] = true
  if (Object.keys(uploadStatuses[filename]).length === chunkTotal) {
    return mergeChunks(filename, chunkTotal)
  }
}

function mergeChunks(filename: string, chunkTotal: number): Promise<void> {
  const outputPath = path.join(UPLOAD_DIR, filename)
  const stream = fs.createWriteStream(outputPath)

  function processChunk(i: number): void {
    if (i >= chunkTotal) {
      stream.end()
      return
    }
    const chunkPath = path.join(UPLOAD_DIR, filename + ".part" + i)
    const inputStream = fs.createReadStream(chunkPath)
    inputStream.pipe(stream)
    inputStream.on("end", () => processChunk(i + 1))
    inputStream.on("error", () => {
      stream.close() // 如果选择结束操作，可以调用 stream.close() 或 stream.destroy()
    })
  }
  processChunk(0)
  return new Promise((resolve, reject) => {
    console.log(resolve)
    stream.end()
    stream.on("error", (err: Error) => reject(err))
  })
}

export default multer({ storage })
